package models;

import static util.FindFoodUtil.empty;
import util.FindFoodUtil;

public enum Category {

	FOOD_BEVERAGE("Food & Beverage", null), BAGELS_DONUTS("Bagels & Donuts",
			FOOD_BEVERAGE), BAKERIES("Bakeries", FOOD_BEVERAGE), BEER_WINE_SPIRITS(
			"Beer, Wine & Spirits", FOOD_BEVERAGE), COFFEE(
			"Cafes, Coffee Houses & Tea Houses", FOOD_BEVERAGE), CHEESE("Cheese",
			FOOD_BEVERAGE), CHOCOLATE("Chocolate", FOOD_BEVERAGE), FARMERS_MARKETS(
			"Farmers' Markets", FOOD_BEVERAGE), ICE_CREAM_PARLORS(
			"Ice Cream Parlors", FOOD_BEVERAGE), JUICE_BARS_SMOOTHIES(
			"Juice Bars & Smoothies", FOOD_BEVERAGE), RESTAURANTS("Restaurants",
			FOOD_BEVERAGE), AMERICAN("American", RESTAURANTS), BARBECUE(
			"Barbecue", RESTAURANTS), BUFFETS("Buffets", RESTAURANTS), BURGERS(
			"Burgers", RESTAURANTS), CHINESE("Chinese", RESTAURANTS), DELIS(
			"Delis", RESTAURANTS), DINERS("Diners", RESTAURANTS), FAST_FOOD(
			"Fast Food", RESTAURANTS), FRENCH("French", RESTAURANTS), INDIAN(
			"Indian", RESTAURANTS), ITALIAN("Italian", RESTAURANTS), JAPANESE(
			"Japanese", RESTAURANTS), KOREAN("Korean", RESTAURANTS), MEXICAN(
			"Mexican", RESTAURANTS), MIDDLE_EASTERN("Middle Eastern", RESTAURANTS), PIZZA(
			"Pizza", RESTAURANTS), STEAKHOUSES("Steakhouses", RESTAURANTS), SUSHI(
			"Sushi", RESTAURANTS), THAI("Thai", RESTAURANTS);

	/**
	 * Splits a Factual-formatted category String into an array of sub-categories.
	 */
	public static String[] splitCategory(String category) {
		if (empty(category))
			return new String[0];
		else
			return category.split("\\W*>\\W*");
	}

	public static Category getByValue(String value) {
		for (Category c : Category.values()) {
			if (c.getValue().equalsIgnoreCase(value))
				return c;
		}
		return null;
	}

	/**
	 * Gets a Category object from a Factual-formatted category String.
	 */
	public static Category getByString(String category) {
		String[] parts = splitCategory(category);
		if (FindFoodUtil.empty(parts))
			return null;

		categoryLoop : for (Category c : Category.values()) {
			// Verify depth match.
			if (c.getDepth() != parts.length)
				continue;

			// Verify all parts match.
			Category current = c;
			int i = 0;
			while (current != null) {
				if (!current.getName().equals(parts[parts.length - 1 - i]))
					continue categoryLoop;
				current = current.getParent();
				i++;
			}
			return c;
		}
		return null;
	}

	private String categoryName;
	private Category parent;
	private int depth;

	Category(String categoryName, Category parent) {
		this.categoryName = categoryName;
		this.parent = parent;
		this.depth = (parent == null) ? 1 : parent.getDepth() + 1;
	}

	public String getValue() {
		return name();
	}

	public String getName() {
		return categoryName;
	}

	public Category getParent() {
		return parent;
	}

	public int getDepth() {
		return depth;
	}

	@Override
	public String toString() {
		StringBuilder s = new StringBuilder();
		Category current = this;
		while (current != null) {
			s.insert(0, current.getName());
			s.insert(0, " > ");
			current = current.getParent();
		}
		if (s.length() > 0)
			s.delete(0, 3);
		return s.toString();
	}
}
